package remato.client.model;

import static remato.client.controller.PrecisePluginImage.IMG_STAKEHOLDER;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;

import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.swt.graphics.Image;
import org.eclipse.ui.views.properties.IPropertySource;

import remato.client.controller.Assert;
import remato.client.controller.RequirementPlugin;
import remato.client.model.facade.IMenuItemsProvider;
import remato.client.model.facade.ModelSystem;
import remato.client.view.util.GenericModelPropertySource;
import remato.client.view.util.ModelItemPropertySource;
import remato.common.domain.helpers.Nameable;
import remato.domain.common.Requirement;
import remato.domain.common.RequirementSystem;
import remato.domain.common.Stakeholder;

import com.wgo.bpot.common.removeme.Persistent;
/**
 *
 *
 * @author Petter L. H. Eide
 * @version $Id: StakeholderWrapper.java,v 1.5 2006-02-19 16:29:37 petterei Exp $
 */
public class StakeholderWrapper extends NodeChild<ModelSystem<StakeholderWrapper>> implements IMenuItemsProvider{

	private static final Class PARENT_INTERFACE = RequirementSystem.class;

	private static Collection<ClientPropertyDefinition<Persistent>> definitions = new ArrayList<ClientPropertyDefinition<Persistent>>();
	
	static {
		PropertySpecification<Persistent> firstName;
		firstName = new PropertySpecification<Persistent>(Configuration.getInstance().getNextStakeholderDefinitionId(), "First name", PropertyType.STRING) {
			@Override
			protected Object getValue(Persistent persistent) {
				return ((Stakeholder)persistent).getFirstName();
			}
			@Override
			protected void setValue(Persistent persistent, Object value) {
				((Stakeholder)persistent).setFirstName((String)value);
			}
		};
		firstName.setDescription("The stakeholders first name.");
		firstName.setPosition(Configuration.getInstance().getNextStakeholderDefinitionPosition());
		firstName.setDefaultValue("No firstname set");
		definitions.add(firstName);
		
		PropertySpecification<Persistent> lastName;
		lastName = new PropertySpecification<Persistent>(Configuration.getInstance().getNextStakeholderDefinitionId(), "Last name", PropertyType.STRING) {
			@Override
			protected Object getValue(Persistent persistent) {
				return ((Stakeholder)persistent).getLastName();
			}
			@Override
			protected void setValue(Persistent persistent, Object value) {
				((Stakeholder)persistent).setLastName((String)value);
			}
		};
		lastName.setDescription("The stakeholders last name.");
		lastName.setPosition(Configuration.getInstance().getNextStakeholderDefinitionPosition());
		lastName.setDefaultValue("No lastname set");
		definitions.add(lastName);
		
		PropertySpecification<Persistent> reporterOrOwnerToRequirements;
		reporterOrOwnerToRequirements = new PropertySpecification<Persistent>(Configuration.getInstance().getNextStakeholderDefinitionId(), "Reporter or Owner to Requirements", PropertyType.REQUIREMENT_COLLECTION){
			@Deprecated // Read-only value, thus should not be used
			@SuppressWarnings("unused") // Read-only value, thus parameters not used
			@Override
			public void setValue(Persistent persistent, Object value) {
				// this value is read only from Stakeholder, it is set and updated from requirement
			}
			@Override
			protected Object getValue(Persistent persistent) {
				Set<Requirement> requirements = ((Stakeholder)persistent).getReporterOrOwnerToRequirements();
				Collection<IAdaptable> wrappers = new ArrayList<IAdaptable>(requirements.size());
				for (Requirement requirement : requirements) {
					RequirementWrapper wrapper = RequirementPlugin.getInstance().getSession().getWrapperFactory().getWrapper(requirement);
					if (null != wrapper) {
						wrappers.add(wrapper);
					} else {
						Assert.warningIfNull(wrapper, "Did not retrieve "+ RequirementWrapper.class.getSimpleName() +" for " + requirement.getName() + " [" +requirement.getDbId() + "]");
					}
				}
				return wrappers;
			}
		};
		reporterOrOwnerToRequirements.setReadOnly(true);
		reporterOrOwnerToRequirements.setDescription("The requirements the stakeholder is owner of or reporter to.");
		reporterOrOwnerToRequirements.setPosition(Configuration.getInstance().getNextStakeholderDefinitionPosition());
		reporterOrOwnerToRequirements.setDefaultValue("None");
		definitions.add(reporterOrOwnerToRequirements);

		PropertySpecification<Persistent> assignedTo;
		assignedTo = new PropertySpecification<Persistent>(Configuration.getInstance().getNextStakeholderDefinitionId(), "Assigned requirements", PropertyType.REQUIREMENT_COLLECTION){
			@Deprecated // Read-only value, thus should not be used
			@SuppressWarnings("unused") // Read-only value, thus parameters not used
			@Override
			public void setValue(Persistent persistent, Object value) {
				// this value is read only from Stakeholder, it is set and updated from requirement
			}
			@Override
			protected Object getValue(Persistent persistent) {
				Set<Requirement> requirements = ((Stakeholder)persistent).getAssignedRequirements();
				Collection<IAdaptable> wrappers = new ArrayList<IAdaptable>(requirements.size());
				for (Requirement requirement : requirements) {
					RequirementWrapper wrapper = RequirementPlugin.getInstance().getSession().getWrapperFactory().getWrapper(requirement);
					if (null != wrapper) {
						wrappers.add(wrapper);
					} else {
						Assert.warningIfNull(wrapper, "Did not retrieve "+ RequirementWrapper.class.getSimpleName() +" for " + requirement.getName() + " [" +requirement.getDbId() + "]");
					}
				}
				return wrappers;
			}
		};
		assignedTo.setReadOnly(true);
		assignedTo.setDescription("The stakeholders assigned requirements.");
		assignedTo.setPosition(Configuration.getInstance().getNextStakeholderDefinitionPosition());
		assignedTo.setDefaultValue("None");
		definitions.add(assignedTo);

		
		PropertySpecification<Persistent> requirementsDefinition;
		requirementsDefinition = new PropertySpecification<Persistent>(Configuration.getInstance().getNextStakeholderDefinitionId(), "Stakeholder to Requirements", PropertyType.REQUIREMENT_COLLECTION) {
			@Override
			protected Object getValue(Persistent persistent) {
				Set<Requirement> requirements = ((Stakeholder)persistent).getStakeholderToRequirements();
				Collection<IAdaptable> wrappers = new ArrayList<IAdaptable>(requirements.size());
				for (Requirement requirement : requirements) {
					RequirementWrapper wrapper = RequirementPlugin.getInstance().getSession().getWrapperFactory().getWrapper(requirement);
					if (null != wrapper) {
						wrappers.add(wrapper);
					} else {
						Assert.warningIfNull(wrapper, "Did not retrieve "+ RequirementWrapper.class.getSimpleName() +" for " + requirement.getName() + " [" +requirement.getDbId() + "]");
					}
				}
				return wrappers;
			}
			@Deprecated // Read-only value, thus should not be used
			@SuppressWarnings("unused") // Read-only value, thus parameters not used
			@Override
			protected void setValue(Persistent persistent, Object value) {
//				if (null != value && value instanceof Collection) {
//					Stakeholder stakeholder = (Stakeholder)persistent;
//					Collection<RequirementWrapper> wrappers = (Collection<RequirementWrapper>)value;
////					Collection<Requirement> iterateWrappers = new HashSet();
////					iterateWrappers.addAll(wrappers);
//					Collection<Requirement> requirements = stakeholder.getStakeholderToRequirements();
//					Collection<Requirement> requirementsToBeRemoved = new HashSet<Requirement>();
//					requirementsToBeRemoved.addAll(requirements);
//					for (RequirementWrapper wrapper : wrappers){
//						Requirement requirement = (Requirement)wrapper.getDomainModelObject();
//						if (requirements.contains(requirement)) {
//							requirementsToBeRemoved.remove(requirement);
//						} else {
//							stakeholder.
//						}
//					}
////					for () {
////						
////					}
//				} else {
//					((Stakeholder)persistent).getStakeholderToRequirements().clear();
//				}
			}
		};
		requirementsDefinition.setReadOnly(true);
		requirementsDefinition.setDescription("The requirements this stakeholder is stakeholder for.");
		requirementsDefinition.setPosition(Configuration.getInstance().getNextStakeholderDefinitionPosition());
		requirementsDefinition.setDefaultValue(null);
		definitions.add(requirementsDefinition);
	}
	
//	private Stakeholder stakeholder;
	
	protected StakeholderWrapper(Stakeholder stakeholder) {
		super(stakeholder, PARENT_INTERFACE, null);
		init(stakeholder);
	}
	protected StakeholderWrapper(Stakeholder stakeholder, StakeholderSystemWrapper wrapper) {
		super(stakeholder, wrapper, PARENT_INTERFACE, null);
	}
	
	/**
	 * @see remato.client.model.NodeChild#init(remato.common.domain.helpers.Nameable)
	 */
	@Override
	protected void init(@SuppressWarnings("unused") Nameable nameable) {
//		this.stakeholder = (Stakeholder)nameable;
		initPropertiesFromDomainObject(definitions);
	}
	
	public int getSortingOrder() {
		return Configuration.STAKEHOLDER_SORT_ORDER;
	}
	
	/**
	 * @see remato.client.model.ClientModelItem#getAdapter(java.lang.Class)
	 */
	@Override
	public Object getAdapter(Class adapter) {
		if (adapter == IPropertySource.class) {
	        List<AbstractPropertySpesification> defs = new ArrayList<AbstractPropertySpesification>();
	        defs.addAll(definitions);
	        defs.add(Configuration.getInstance().getNodeDescriptionSpecification());
			ModelItemPropertySource propertySource = new GenericModelPropertySource(this, defs, "Stakeholder properties");
			return propertySource;
		} 
		return super.getAdapter(adapter);
	}

	@Override
	public Image getImage() {
		return IMG_STAKEHOLDER.getImage();
	}
	
}
